/*
Promise.all()方法接受一个Promise对象的数组作为参数，当这个数组里的所有Promise对象全部变为resolve或reject状态时，Promise.all()返回一个新的Promise对象。
这个新的Promise对象会按照传入的Promise数组的顺序，把每个Promise对象的返回值放到一个数组中，传给新的Promise对象的then()方法。
如果传入的所有Promise对象都变为resolve状态，新的Promise对象就变为resolve状态；只要有一个Promise对象变为reject状态，新的Promise对象就变为reject状态。
Promise.all的返回值也是一个Promise
 */
// 接收数组作为参数
function myPromiseAll(promises) {
    // 该方法返回一个promise对象
    return new Promise((resolve, reject) => {
        // 该方法的参数需为一个可迭代对象
        if (promises == null || typeof promises[Symbol.iterator] !== "function") {
            throw new TypeError(`${promises} is not a iterable`);
        }
        // 这是转换Set和Map的操作吧
        promises = [...promises];

        // 可迭代对象为空则返回已resolve的promise
        if (promises.length === 0) {
            resolve([]);
        }

        let count = 0;
        const values = [];
        promises.forEach((promise, index) => {
            // 保证可迭代对象的元素为promise，使用Promise.resolve()处理
            // Promise.resolve()是返回一个已经执行完成（即已经 resolved）的 Promise 对象。**如果给定一个 Promise 对象作为参数，则返回这个 Promise 对象本身**
            // 那么就相当于这个Promise本身再.then() 那么如果这里存在reject 则会执行.catch 执行reject函数 相当于执行此promise(promises)
            Promise.resolve(promise)
                .then((res) => {
                    values[index] = res;
                    // 这里是全是fulfilled情况(长度才会相等) 调用resolve函数(测试用例这里就是一个打印)
                    if (++count === promises.length) resolve(values);
                }, reject) // 进入then函数 如果then前为reject 则执行then的第二个回调函数reject  在then内部会执行reject(this.value) 即reject('error') 所以导致promiseAll的状态是reject 所以会执行测试用例里的catch
                // 相当于执行当前promise(也就是代码里的promises) Promise.reject("error").catch(reject) reject的参数自然是"error"
                // .catch(reject);
        });
    });
};

// 示例使用
var promise1 = Promise.resolve(1);
var promise2 = Promise.resolve(2);
// var promise3 = Promise.reject("error");
var promise4 = Promise.resolve(4);
myPromiseAll([promise1, promise2, promise3, promise4]).then(function(values) {
    console.log(values); // ["1", "2", "error", "4"]
}).catch(function(error) {
    console.error(error); // "error"
});
